grammar TTCN3Grammar;

options {
backtrack=true; 
//memoize=true;
// output = AST;
 //language=java;
}

tokens  {
AddressValue=	'null';
OmitKeyword=	'omit';
InParKeyword=	'in';
OutParKeyword=	'out';
InOutParKeyword =	'inout';
TypeDefKeyword = 'type';
OptionalKeyword = 'optional';
UnionKeyword = 'union';
SetKeyword = 'set';
OfKeyword = 'of';
EnumKeyword = 'enumerated';
LengthKeyword = 'length';
PortKeyword = 'port';
MessageKeyword = 'message';
AllKeyword = 'all';
ProcedureKeyword = 'procedure';
MixedKeyword = 'mixed';
ComponentKeyword = 'component';
ExtendsKeyword = 'extends';
ConstKeyword = 'const';
TemplateKeyword = 'template';
ModifiesKeyword = 'modifies';
PatternKeyword = 'pattern';
ComplementKeyword = 'complement';
SubsetKeyword = 'subset';
SupersetKeyword = 'superset';
PermutationKeyword = 'permutation';
IfPresentKeyword = 'ifpresent';
InfinityKeyword = 'infinity';
MatchKeyword = 'match';
ValueofKeyword = 'valueof';
FunctionKeyword = 'function';
ReturnKeyword = 'return';
RunsKeyword = 'runs';
OnKeyword = 'on';
SignatureKeyword = 'signature';
NoBlockKeyword = 'noblock';
ExceptionKeyword = 'exception';
TestcaseKeyword = 'testcase';
SystemKeyword ='system';
ExecuteKeyword = 'execute';
AltstepKeyword = 'altstep';
ImportKeyword = 'import';
ExceptKeyword = 'except';
RecursiveKeyword = 'recursive';
GroupKeyword = 'group';
ExtKeyword = 'external';
ModuleParKeyword = 'modulepar';
ControlKeyword = 'control';
VarKeyword = 'var';
TimerKeyword = 'timer';
SelfKeyword = 'self';
DoneKeyword = 'done';
KilledKeyword = 'killed';
MTCKeyword = 'mtc';
RunningKeyword = 'running';
CreateKeyword = 'create';
AliveKeyword = 'alive';
ConnectKeyword = 'connect';
DisconnectKeyword = 'disconnect';
MapKeyword = 'map';
UnmapKeyword = 'unmap';
StartKeyword = 'start';
StopKeyword = 'stop';
KillKeyword = 'kill';
PortSendKeyword = 'send';
ToKeyword = 'to';
CallOpKeyword = 'call';
NowaitKeyword = 'nowait';
ReplyKeyword = 'reply';
RaiseKeyword = 'raise';
ReceiveOpKeyword = 'receive';
FromKeyword = 'from';
ValueKeyword ='value';
SenderKeyword = 'sender';
TriggerOpKeyword = 'trigger';
GetCallOpKeyword = 'getcall';
ParamKeyword = 'param';
GetReplyOpKeyword = 'getreply';
CheckOpKeyword = 'check';
CatchOpKeyword =	'catch';
ClearOpKeyword = 'clear';
AnyKeyword = 'any';
ReadKeyword =	'read';
TimeoutKeyword = 'timeout';
BitStringKeyword =	'bitstring';
BooleanKeyword =	'boolean';
CharStringKeyword = 'charstring';
UniversalKeyword =	'universal';
OctetStringKeyword =	'octetstring';
HexStringKeyword =	'hexstring';
VerdictTypeKeyword =	'verdicttype';
FloatKeyword =	'float';
DefaultKeyword =	'default';
AnyTypeKeyword =	'anytype';
IntegerKeyword = 'integer';
CharKeyword =	'char';
WithKeyword =	'with';
EncodeKeyword =	'encode';
VariantKeyword =	'variant';
DisplayKeyword =	'display';
ExtensionKeyword =	'extension';
OverrideKeyword =	'override';
SetVerdictKeyword =	'setverdict';
GetLocalVerdict = 'getverdict';
ActionKeyword =	'action';
AltKeyword =	'alt';
InterleavedKeyword =	'interleave';
LabelKeyword =	'label';
GotoKeyword =	'goto';
ActivateKeyword =	'activate';
DeactivateKeyword =	'deactivate';
LogKeyword =	'log';
ForKeyword =	'for';
DoKeyword =	'do';
WhileKeyword =	'while';
IfKeyword =	'if';
ElseKeyword =	'else';
SelectKeyword =	'select';
CaseKeyword =	'case';
Ttcn3ModuleKeyword = 'module' ;
LanguageKeyword = 'language';
RecordKeyword  = 'record' ;
AddressKeyword =	'address';

AnyValue  =  '?';
AnyOrOmit =  '*';
PortRedirectSymbol =  '->';
//Exponential = 'E';
Dot = '.';
//Dash:		'-';
//Minus :	'-';
SemiColon = ';' ;
Colon = ':';
Underscore = '_';
AssignmentChar = ':=';
}


@header {
//package org.yatr.language;

//import org.yatr.tci.*;
import org.antlr.stringtemplate.*;
}

@members {
	public void ttcnEcho(final String str) {
		System.out.println(str);
	}
}

ttcn3File
	:	ttcn3Modules
	|	EOF
	;
ttcn3Modules
	:	ttcn3Module ttcn3Modules
	|
	;

ttcn3Module
	:	Ttcn3ModuleKeyword ttcn3ModuleId {ttcnEcho("module def:"+$ttcn3ModuleId.text);}
		'{' 
		  moduleDefinitionsPart?
		  moduleControlPart?
		'}'
		withStatement? SemiColon?
	;

ttcn3ModuleId :  moduleId ;
moduleId 
	: globalModuleId languageSpec? 
	;
globalModuleId : moduleIdentifier ;
moduleIdentifier : ID ;

languageSpec : LanguageKeyword freeText
	;

/**
Module definition parts
*/
//General
moduleDefinitionsPart : moduleDefinitionsList ;
moduleDefinitionsList : (moduleDefinition SemiColon?)+ ;	//SemiColon?
moduleDefinition 
	:  (typeDef | constDef | templateDef | moduleParDef 
	    | functionDef | signatureDef | testcaseDef | altstepDef
	    | importDef | groupDef | extFunctionDef | extConstDef)  
	   withStatement? 
	;

//Typedef definition
typeDef
	: TypeDefKeyword typeDefBody
	;

typeDefBody
	: (RecordKeyword | UnionKeyword | SetKeyword |
	   EnumKeyword   | PortKeyword  | ComponentKeyword
	  ) => structuredTypeDef
	| subTypeDef
	;

structuredTypeDef
options{k=1;}
	: setDef
	| unionDef
	| recordDef
	| recordOfDef
	| setOfDef
	| enumDef
	| portDef
	| componentDef
	;

recordDef
	: RecordKeyword structDefBody
	;

structDefBody
	: ( (AddressKeyword)=>AddressKeyword 
	   | structTypeIdentifier (structDefFormalParList)? 
	  )
	  '{'
	      ( structFieldDef (',' structFieldDef)* )?
	  '}'
	;
structTypeIdentifier : ID;

structDefFormalParList
	: '(' structDefFormalPar (',' structDefFormalPar)* ')'
	;
structDefFormalPar
	: formalValuePar	/* static semantics, formalValuePar shall resolve to an parameter */
	;

structFieldDef
	: (type | nestedTypeDef) structFieldIdentifier (arrayDef)? (subTypeSpec)? 
	  (OptionalKeyword)?
	;

nestedTypeDef
	: nestedRecordDef | nestedSetDef | nestedRecordOfDef | nestedSetOfDef
	| nestedUnionDef | nestedEnumDef
	;
	
nestedRecordDef
	: RecordKeyword '{' ( structFieldDef (',' structFieldDef)* )? '}'
	;
nestedUnionDef
	: UnionKeyword '{' (unionFieldDef (',' unionFieldDef)* )? '}'
	;
nestedSetDef
	: SetKeyword '{' (structFieldDef (',' structFieldDef)* )? '}'
	;
nestedRecordOfDef
	: RecordKeyword (stringLength)? OfKeyword (type | nestedTypeDef)
	;
nestedSetOfDef
	: SetKeyword  (stringLength)? OfKeyword (type | nestedTypeDef)
	;
nestedEnumDef
	: EnumKeyword '{' enumerationList  '}'
	;

structFieldIdentifier : ID ;

unionDef
	: UnionKeyword unionDefBody
	;
unionDefBody
	: (structTypeIdentifier (structDefFormalParList)? | AddressKeyword)
	  '{' unionFieldDef (',' unionFieldDef)*
	  '}'
	;
unionFieldDef
	: (type | nestedTypeDef ) structFieldIdentifier (arrayDef)?  (subTypeSpec)?
	;

setDef
	: SetKeyword structDefBody
	;
	
recordOfDef
	: RecordKeyword (stringLength)? OfKeyword structOfDefBody
	;
structOfDefBody
	: (type | nestedTypeDef)  (structTypeIdentifier | AddressKeyword) (subTypeSpec)?
	;
	
setOfDef
	: SetKeyword (stringLength)? OfKeyword structOfDefBody
	;

enumDef
	: EnumKeyword (enumTypeIdentifier | AddressKeyword) 
	  '{' enumerationList
	  '}'
	;

enumTypeIdentifier
	: ID;
enumerationList
	: enumeration (',' enumeration)*
	;
enumeration
	: enumerationIdentifier  ('(' ( '-' )? Number ')')?
	;
enumerationIdentifier
	: ID;

subTypeDef
	: type (subTypeIdentifier | AddressKeyword)  (arrayDef)? (subTypeSpec)?
	;
subTypeIdentifier
	: ID
	;

/** Static  semantics - allowedValues shall be of the type as the field being subtyped*/
subTypeSpec
	: ('(') => allowedValues (stringLength)? 
	| (LengthKeyword)=> stringLength
	;
allowedValues 
	: '(' 
	     ( (PatternKeyword)=>charStringMatch
	     | valueOrRange (',' valueOrRange)* 
	     ) 
	  ')'
	;

valueOrRange
	: (lowerBound '..') => rangeDef 
	| constantExpression
	;
/** static semantics - rangeDef production  shall only be used with integer , charstring ,
universal charstring , float based type
static semantics - When subtyping charstring or universal charstring range and vlaues
shall not be mixed in the same subTypeSpec */
rangeDef
	: lowerBound '..' upperBound
	;
/** static semantics - stringLength shall only be used with string types or to limit setof
/record of. singleConstExpression and upperBound shall evaluate to non-negative integer
values, in case of upperBound including infinity */
stringLength
	: LengthKeyword '(' singleConstExpression ('..' upperBound)? ')'
	;



portType
	: (globalModuleId Dot)? portTypeIdentifier
	;
	
portDef
	: PortKeyword portDefBody
	;
portDefBody
	: portTypeIdentifier portDefAttribs
	;

portTypeIdentifier
	: ID;
portDefAttribs
	: messageAttribs | procedureAttribs | mixedAttribs
	;
messageAttribs
	: MessageKeyword 
	  '{' (messageList SemiColon?)+
	  '}'
	;
messageList
	: direction allOrTypeList
	;
direction
	: InParKeyword | OutParKeyword | InOutParKeyword
	;

allOrTypeList
	: AllKeyword | typeList
	;
/* the use of allKeyWord in port definitions is deprecated */

typeList
	: type (',' type)*
	;

procedureAttribs
	: ProcedureKeyword
	  '{' (procedureList SemiColon?)+
	  '}'
	;

procedureList
	: direction allOrSignatureList
	;
allOrSignatureList
	: AllKeyword | signatureList
	;
signatureList
	: signature (',' signature)*
	;

mixedAttribs
	: MixedKeyword
	  '{' (mixedList SemiColon?)+
	  '}'
	;

mixedList
	: direction procOrTypeList
	;
procOrTypeList
	: AllKeyword | procOrType (',' procOrType)*
	;

procOrType
	: signature | type
	;


componentDef
	: ComponentKeyword componentTypeIdentifier
	    (ExtendsKeyword componentType (',' componentType)*)?
	  '{' componentDefList?
	  '}'
	;
componentTypeIdentifier
	: ID;
componentType
	: (globalModuleId Dot)? componentTypeIdentifier
	;
componentDefList
	: (componentElementDef SemiColon? )*
	;
componentElementDef
	: portInstance | varInstance | timerInstance | constDef
	;
portInstance
	: PortKeyword portType portElement (',' portElement)*
	;
portElement
	: portIdentifier (arrayDef)?
	;
portIdentifier
	: ID;


/**
 * Constant definitions
 */
constDef
	: ConstKeyword type constList
	;
constList
	: singleConstDef (',' singleConstDef)*
	;
/** Static semantics - the value of constantExpression shall be of the same type 
 as the stated type for the Constant */
singleConstDef
	: constIdentifier (arrayDef)? AssignmentChar  constantExpression
	;
constIdentifier
	: ID;



/**
 * Template definitions.
 */
templateDef
	: TemplateKeyword baseTemplate (derivedDef)?  AssignmentChar templateBody
	;
baseTemplate
	: (type | signature) templateIdentifier ( '(' templateFormalParList ')' )?
	;
templateIdentifier
	: ID;
derivedDef
	: ModifiesKeyword  templateRef
	;


templateFormalParList
	: templateFormalPar (',' templateFormalPar)*
	;
/** static semantics - formalValuePar shall resolve to an IN parameter  */
templateFormalPar
	: formalValuePar | formalTemplatePar
	;
templateBody
	: (simpleSpec | fieldSpecList | arrayValueOrAttrib)
	| (extraMatchingAttributes)?
	;
simpleSpec
	: singleValueOrAttrib
	;
fieldSpecList
	: '{' fieldSpec (',' fieldSpec)* '}'
	;
fieldSpec
	: fieldReference AssignmentChar templateBody
	;
/** static semantics - Within fieldReference, arrayOrBitRef can be used for record of and
set of  templates/template fields in modified templates only*/
fieldReference
	: structFieldRef | arrayOrBitRef | parRef
	;
/** static semantics - predefinedType and typeReference shall be used for anytype value 
notation only,  predefinedType shall not be AnytypeKeyword. */
structFieldRef
	: structFieldIdentifier | predefinedType	| typeReference
	;

/** static semantics -  signatureParIdentifier shall be a formal parameter identifier from
the associated signature definition*/
parRef
	: signatureParIdentifier
	;
signatureParIdentifier
	: valueParIdentifier
	;

/** static semantics -  arrayRef shall be optionally used for array types and ASN.1 SET OF
and SEQUENCE OF and TTCN-3 record of and set of . The same notation can be used for a
bit reference inside an ASN.1 and TTCN-3 bitstring type */
arrayOrBitRef
	: '[' fieldOrBitNumber ']'
	;
/** static semantics - singleExpression will resolve to a value of integer type. */
fieldOrBitNumber
	: singleExpression
	;
/** static semantics - variableIdentifier (accessed via singleExpression) may only be used
in in-line template definitions to reference variable in the current scope*/
singleValueOrAttrib
	: matchingSymbol | singleExpression | templateRefWithParList
	;
arrayValueOrAttrib
	: '{' arrayElementSpecList '}'
	;
arrayElementSpecList
	: arrayElementSpec (',' arrayElementSpec)*
	;
arrayElementSpec
	: notUsedSymbol | permutationMatch | templateBody
	;
notUsedSymbol
	: '-'	//Dash
	;
matchingSymbol
	: complement | AnyValue | AnyOrOmit | valueOrAttribList | range | bitStringMatch
	| hexStringMatch | octetStringMatch | charStringMatch | subsetMatch | supersetMatch
	;
extraMatchingAttributes
	: lengthMatch | ifPresentMatch | lengthMatch ifPresentMatch
	;
bitStringMatch
	: '\'' (binOrMatch)* '\'' 'B'
	;
binOrMatch
	: Bin | AnyValue | AnyOrOmit
	;
hexStringMatch
	: '\''  (hexOrMatch)* '\'' 'H'
	;
hexOrMatch
	: Hex | AnyValue | AnyOrOmit
	;
octetStringMatch
	: '\'' (octOrMatch)* '\'' 'O'
	;
octOrMatch
	: Oct | AnyValue | AnyOrOmit
	;
charStringMatch
	: PatternKeyword Cstring
	;

complement
	: ComplementKeyword valueList
	;

valueList
	: '(' constantExpression (',' constantExpression)* ')'
	;
/** static semantics - superset and subset matching shell only be used with 
the set of type. */
subsetMatch
	: SubsetKeyword valueList
	;
supersetMatch
	: SupersetKeyword valueList
	;



permutationMatch
	: PermutationKeyword permutationList
	;

/** static semantics - restrictions on the content of templateBody are given in B.1.3.3 */
permutationList
	: '(' templateBody (',' templateBody)* ')'
	;

valueOrAttribList
	: '(' templateBody (',' templateBody )* ')'
	;
lengthMatch
	: stringLength;
ifPresentMatch
	: IfPresentKeyword
	;

range
	: '(' lowerBound '..' upperBound ')'
	;
/** static semantics - lowerBound and upperBound shall evaluate to type integer , charstring
and uniserval charstring or float. In case lowerBound or upperBound  evaluates to charstring 
or universal charstring, only singleConstExpression may be present and the string length 
shall be 1.*/
lowerBound
	: singleConstExpression |  '-'  InfinityKeyword
	;
upperBound
	: singleConstExpression | InfinityKeyword
	;


templateInstance
	: inLineTemplate
	;
templateRefWithParList
	: (globalModuleId Dot)? templateIdentifier (templateActualParList)?
	| templateParIdentifier
	;
templateRef
	: (globalModuleId Dot)? templateIdentifier
	| templateParIdentifier
	;
/** static semantics - The type field may only be omited when the type is implicitly 
unambigous.*/
inLineTemplate
	: ( (type | signature) Colon )?  ( derivedRefWithParList  AssignmentChar)? 
	  templateBody
	;
derivedRefWithParList
	: ModifiesKeyword templateRefWithParList
	;
templateActualParList
	: '(' templateActualPar (',' templateActualPar)* ')'
	;
/** static semantics - When the corresponding formal parameter is not of template type
the templateInstance production shall resolve to one or more singleExpression. */
templateActualPar 
	: templateInstance
	;

templateOps
	: matchOp | valueofOp
	;
/** static semantics - The type of the value returned by the expression must be the same
as the template type and each field of the template shall resolve to a single value*/
matchOp
	: MatchKeyword '(' expression ',' templateInstance ')'
	;

valueofOp
	: ValueofKeyword '(' templateInstance ')'
	;


/**
 * function definitions.
 */
functionDef
	: FunctionKeyword functionIdentifier  {ttcnEcho("\tfunc def:"+$functionIdentifier.text);}
	  '(' functionFormalParList? ')' (runsOnSpec)? (returnType)?
	  statementBlock
	;

functionIdentifier
	: ID;
functionFormalParList
	: functionFormalPar (',' functionFormalPar)*
	;
functionFormalPar
	: formalValuePar
	| formalTimerPar
	| formalTemplatePar
	| formalPortPar
	;
/** static semantics - the use of the TemplateKeyword shall conform to 
restrictions in clause 16.1.0  */
returnType
	: ReturnKeyword (TemplateKeyword)? type
	;

runsOnSpec
	: RunsKeyword OnKeyword componentType
	;

statementBlock
	: '{' functionStatementOrDefList? '}'
	;
functionStatementOrDefList
	: (functionStatementOrDef (SemiColon)? )+
	;
functionStatementOrDef
	: functionLocalDef
	| functionLocalInst
	| functionStatement
	;
functionLocalDef
	: constDef | templateDef
	;
functionLocalInst
	: varInstance | timerInstance
	;
functionStatement
//options{k=3;}
	: configurationStatements
	| timerStatements
	| communicationStatements
	| basicStatements
	| behaviourStatements
	| verdictStatements
	| sUTStatements
	;

functionInstance
	: functionRef '(' (functionActualParList)? ')'
	;
functionRef
	: (globalModuleId Dot)? (functionIdentifier | extFunctionIdentifier)
	| preDefFunctionIdentifier
	;
preDefFunctionIdentifier
	: ID;
functionActualParList
	: functionActualPar (',' functionActualPar)*
	;
/** static semantics - When the corresponding formal parameter is not of
template type the templateInstance production shall resolve to one or more
singleExpressions i.e. equivalent to the expression production */
functionActualPar
	: timerRef | templateInstance | port | componentRef
	;


/**
 * signature definitions
 */
signatureDef
	: SignatureKeyword signatureIdentifier
	  '(' (signatureFormalParList)? ')'  (returnType | NoBlockKeyword)? exceptionSpec?
	;

signatureIdentifier
	: ID;
signatureFormalParList
	: signatureFormalPar (',' signatureFormalPar)*
	;
signatureFormalPar
	: formalValuePar
	;

exceptionSpec
	: ExceptionKeyword '(' exceptionTypeList ')'
	;

exceptionTypeList
	: type (',' type)*
	;
signature
	: (globalModuleId Dot)? signatureIdentifier
	;


/**
 * testcase definitions.
 */
 testcaseDef
 	: TestcaseKeyword testcaseIdentifier {ttcnEcho("\ttestcase def:"+$testcaseIdentifier.text);}
 	  '(' testcaseFormalParList? ')' configSpec
 	  statementBlock
 	;

 testcaseIdentifier
 	: ID;
 testcaseFormalParList
 	: testcaseFormalPar (',' testcaseFormalPar)*
 	;
 testcaseFormalPar
 	: formalValuePar 
 	| formalTemplatePar
 	;
 configSpec
 	: runsOnSpec (systemSpec)?
 	;
 systemSpec
 	: SystemKeyword componentType
 	;

 
 testcaseInstance
 	: ExecuteKeyword '(' testcaseRef '(' (testcaseActualParList)? ')'  (',' timerValue)? ')'
 	;

 testcaseRef
 	: (globalModuleId Dot)? testcaseIdentifier
 	;
 testcaseActualParList
 	: testcaseActualPar (',' testcaseActualPar)*
 	;
 testcaseActualPar
 	: templateInstance
 	;
 
 /**
  * Altstep definitions.
  */
altstepDef
	: AltstepKeyword altstepIdentifier {ttcnEcho("\taltstep def:"+$altstepIdentifier.text);}
	  '(' (altstepFormalParList)? ')'   (runsOnSpec)?
	  '{' altstepLocalDefList altGuardList
	  '}'
	;

altstepIdentifier
	: ID;
/** static semantics - altstep that are activated as defaults shall only have IN parameters*/
altstepFormalParList
	: functionFormalParList
	;
altstepLocalDefList
	: (altstepLocalDef (SemiColon)? )*
	;
altstepLocalDef
	: varInstance | timerInstance | constDef | templateDef
	;
/** static semantics - all timer instance in functionActualParList shall be declared  as 
component local timers (see also production componentElementDef ) */
altstepInstance
	: altstepRef '(' functionActualParList? ')'
	;
altstepRef
	: (globalModuleId Dot)? altstepIdentifier
	;


/**
 * Import definitions.
 */
importDef
	: ImportKeyword importFromSpec (allWithExcepts | '{' importSpec '}')
	;

allWithExcepts
	: AllKeyword (exceptsDef)?
	;
exceptsDef
	: ExceptKeyword '{' exceptSpec '}'
	;

exceptSpec
	: (exceptElement (SemiColon)? )*
	;
exceptElement
	: exceptGroupSpec
	| exceptTypeDefSpec
	| exceptConstSpec
	| exceptTemplateSpec
	| exceptTestcaseSpec
	| exceptAltstepSpec
	| exceptFunctionSpec
	| exceptModuleParSpec
	| exceptSignatureSpec
	;
exceptGroupSpec : GroupKeyword (exceptGroupRefList | AllKeyword);
exceptTypeDefSpec : TypeDefKeyword (exceptGroupRefList | AllKeyword);
exceptConstSpec : ConstKeyword (exceptGroupRefList | AllKeyword);
exceptTemplateSpec : TemplateKeyword (exceptGroupRefList | AllKeyword);
exceptTestcaseSpec : TestcaseKeyword (exceptGroupRefList | AllKeyword);
exceptAltstepSpec : AltstepKeyword (exceptGroupRefList | AllKeyword);
exceptFunctionSpec : FunctionKeyword (exceptGroupRefList | AllKeyword);
exceptModuleParSpec : ModuleParKeyword (exceptGroupRefList | AllKeyword);
exceptSignatureSpec : SignatureKeyword (exceptGroupRefList | AllKeyword);

importSpec
	: (importElement (SemiColon)? )*
	;
importElement
	: importGroupSpec
	| importTypeDefSpec
	| importTemplateSpec
	| importConstSpec
	| importTestcaseSpec
	| importAltstepSpec
	| importFunctionSpec
	| importSignatureSpec
	| importModuleParSpec
	;
/** NOTE: RecursiveKeyword is deprecated */
importFromSpec
	: FromKeyword moduleId (RecursiveKeyword)?
	;

importGroupSpec
	: GroupKeyword (groupRefListWithExcept | allGroupsWithExcept)
	;
groupRefList
	: fullGroupIdentifier (',' fullGroupIdentifier)*
	;
groupRefListWithExcept
	: fullGroupIdentifierWithExcept (',' fullGroupIdentifierWithExcept)*
	;
allGroupsWithExcept
	: AllKeyword (ExceptKeyword groupRefList)?
	;
fullGroupIdentifier
	: groupIdentifier (Dot groupIdentifier)*
	;
fullGroupIdentifierWithExcept
	: fullGroupIdentifier (exceptsDef)?
	;
exceptGroupRefList
	: exceptFullGroupIdentifier (',' exceptFullGroupIdentifier)*
	;
exceptFullGroupIdentifier
	: fullGroupIdentifier
	;

importTypeDefSpec
	: TypeDefKeyword (typeRefList | allTypesWithExcept)
	;
typeRefList
	: typeDefIdentifier (',' typeDefIdentifier)*
	;
allTypesWithExcept
	: AllKeyword (ExceptKeyword typeRefList)
	;
typeDefIdentifier
	: structTypeIdentifier
	| enumTypeIdentifier
	| portTypeIdentifier
	| componentTypeIdentifier
	| subTypeIdentifier
	;

importTemplateSpec
	: TemplateKeyword (templateRefList | allTemplsWithExcept)
	;
templateRefList
	: templateIdentifier (',' templateIdentifier)
	;
allTemplsWithExcept
	: AllKeyword (ExceptKeyword templateRefList)?
	;
	
importConstSpec
	: ConstKeyword (constRefList | allConstsWithExcept)
	;
constRefList
	: constIdentifier (',' constIdentifier)*
	;
allConstsWithExcept
	: AllKeyword (ExceptKeyword constRefList)?
	;

importAltstepSpec
	: AltstepKeyword (altstepRefList | allAltstepsWithExcept)
	;
altstepRefList
	: altstepIdentifier (',' altstepIdentifier)*
	;
allAltstepsWithExcept
	: AllKeyword (ExceptKeyword altstepRefList)?
	;

importTestcaseSpec
	: TestcaseKeyword (testcaseRefList | allTestcasesWithExcept)
	;
testcaseRefList
	: testcaseIdentifier (',' testcaseIdentifier)*
	;
allTestcasesWithExcept
	: AllKeyword (ExceptKeyword testcaseRefList)?
	;

importFunctionSpec
	: FunctionKeyword (functionRefList | allFunctionsWithExcept)
	;
functionRefList
	: functionIdentifier (',' functionIdentifier)*
	;
allFunctionsWithExcept
	: AllKeyword (ExceptKeyword functionRefList)?
	;

importSignatureSpec
	: SignatureKeyword (signatureRefList | allSignaturesWithExcept)
	;
signatureRefList
	: signatureIdentifier (',' signatureIdentifier)*
	;
allSignaturesWithExcept
	: AllKeyword (ExceptKeyword signatureRefList)?
	;

importModuleParSpec
	: ModuleParKeyword (moduleParRefList | allModuleParWithExcept)
	;
moduleParRefList
	: moduleParIdentifier (',' moduleParIdentifier)*
	;
allModuleParWithExcept
	: AllKeyword (ExceptKeyword moduleParRefList)?
	;

/**
 * Group definitions.
 */
groupDef
	: GroupKeyword groupIdentifier
	  '{' moduleDefinitionsPart?
	  '}'
	;

groupIdentifier
	: ID;

/**
 * External function definitions.
 */
extFunctionDef
	: ExtKeyword FunctionKeyword extFunctionIdentifier 
	  '(' functionFormalParList? ')' (returnType)?
	;

extFunctionIdentifier
	: ID;

/**
 * External const definitions
 */
extConstDef
	: ExtKeyword ConstKeyword type extConstIdentifier
	;
extConstIdentifier
	: ID;

/**
 * Module parameter definitions.
 */
moduleParDef
	: ModuleParKeyword (modulePar | '{' multitypedModuleParList '}' )
	;

multitypedModuleParList
	: (modulePar SemiColon)+
	;
modulePar
	: moduleParType moduleParList
	;
/** static semantics - type shall not be of component/default/anytype. Type shall only
resolve to address type if a definition for the address type is defined within the module*/
moduleParType
	: type
	;
moduleParList
	: moduleParIdentifier (AssignmentChar constantExpression)?  
	  (',' moduleParIdentifier (AssignmentChar constantExpression)? )*
	;
 moduleParIdentifier
 	: ID;


/**
 * Control part.
 */
moduleControlPart
	: ControlKeyword  '{' moduleControlBody '}' (withStatement)? (SemiColon)?
	;

moduleControlBody
	: (controlStatementOrDefList)?
	;
controlStatementOrDefList
	: (controlStatementOrDef (SemiColon)?)+
	;
controlStatementOrDef
	: functionLocalDef
	| functionLocalInst
	| controlStatement
	;
controlStatement
	: timerStatements
	| basicStatements
	| behaviourStatements
	| sUTStatements
	| StopKeyword
	;

/**
 * Variable instantiation
 */
varInstance
	: VarKeyword
	(  type varList 
	 | TemplateKeyword type tempVarList
	)
	;
varList
	: singleVarInstance (',' singleVarInstance)*
	;
singleVarInstance
	: varIdentifier (arrayDef)? (AssignmentChar varInitialValue)?
	;
varInitialValue
	: expression
	;

varIdentifier
	: ID;
tempVarList
	: singleTempVarInstance (',' singleTempVarInstance)*
	;
singleTempVarInstance
	: varIdentifier (arrayDef)? (AssignmentChar tempVarInitialValue)?
	;
tempVarInitialValue
	: templateBody
	;

variableRef
	: (varIdentifier | valueParIdentifier) (extendedFieldReference)?
	;

/**
 * Timer instantiation.
 */
timerInstance
	: TimerKeyword timerList
	;
timerList
	: singleTimerInstance (',' singleTimerInstance)*
	;
singleTimerInstance
	: timerIdentifier (arrayDef)? (AssignmentChar timerValue)?
	;

timerIdentifier
	: ID;
/** some static semantics here! */
timerValue
	: expression
	;

timerRef 
	: (timerIdentifier | timerParIdentifier) (arrayOrBitRef)*
	;

/**
 * Component operations.
 */
configurationStatements
	: connectStatement
	| disconnectStatement
	| mapStatement
	| unmapStatement
	| doneStatement
	| killedStatement
	| startTCStatement
	| stopTCStatement
	| killTCStatement
	;
configurationOps
	: createOp | SelfKeyword | SystemKeyword | MTCKeyword | runningOp | aliveOp
	;
// restricted on singleExpression see in 22.1
createOp
	: componentType Dot CreateKeyword ( '(' singleExpression ')' )?  AliveKeyword?
	;



doneStatement
	: componentID Dot DoneKeyword
	;
killedStatement
	: componentID Dot KilledKeyword
	;
componentID
	: componentOrDefaultReference | (AnyKeyword | AllKeyword) ComponentKeyword
	;

runningOp
	: componentID Dot RunningKeyword
	;

aliveOp
	: componentID Dot AliveKeyword
	;

connectStatement
	: ConnectKeyword singleConnectionSpec
	;

singleConnectionSpec
	: '(' portRef ',' portRef ')'
	;
portRef
	: componentRef Colon port
	;
componentRef
	: componentOrDefaultReference | SystemKeyword | SelfKeyword | MTCKeyword
	;
disconnectStatement
	: DisconnectKeyword (singleOrMultiConnectionSpec)? 
	;
singleOrMultiConnectionSpec
	: singleConnectionSpec
	| allConnectionsSpec
	| allPortsSpec
	| allCompsAllPortsSpec
	;
allConnectionsSpec
	: '(' portRef ')'
	;
allPortsSpec
	: '(' componentRef ':' AllKeyword PortKeyword ')'
	;
allCompsAllPortsSpec
	: '(' AllKeyword ComponentKeyword ':'  AllKeyword PortKeyword ')'
	;

mapStatement
	: MapKeyword singleConnectionSpec
	;

unmapStatement
	: UnmapKeyword (singleOrMultiConnectionSpec)?
	;

// some static semantics here
startTCStatement
	: componentOrDefaultReference Dot StartKeyword '(' functionInstance ')'
	;

stopTCStatement
	: StopKeyword
	| componentReferenceOrLiteral Dot StopKeyword
	| AllKeyword ComponentKeyword Dot StopKeyword
	;

componentReferenceOrLiteral
	: componentOrDefaultReference
	| MTCKeyword
	| SelfKeyword
	;
killTCStatement
	: KillKeyword
	| componentReferenceOrLiteral KillKeyword
	| AllKeyword ComponentKeyword Dot KillKeyword
	;

//some static semantics here
componentOrDefaultReference
	: variableRef
	| functionInstance
	;

/**
 * Port operations
 */
port:	(portIdentifier | portParIdentifier) (arrayOrBitRef)?
	;
/*
communicationStatements
	: (port Dot PortSendKeyword) => sendStatement
	| (port Dot CallOpKeyword) => callStatement
	| (port Dot ReplyKeyword) => replyStatement
	| (port Dot RaiseKeyword) => raiseStatement
	| (portOrAny Dot ReceiveOpKeyword) => receiveStatement
	| (portOrAny Dot TriggerOpKeyword) => triggerStatement
	| (portOrAny Dot GetCallOpKeyword) => getCallStatement
	| (portOrAny Dot GetReplyOpKeyword) => getReplyStatement
	| (portOrAny Dot CatchOpKeyword) => catchStatement
	| (portOrAny Dot CheckOpKeyword) => checkStatement
	| (portOrAll   Dot ClearOpKeyword) => clearStatement
	| (portOrAll   Dot StartKeyword) => startStatement
	| (portOrAll   Dot StartKeyword) => stopStatement
	;
*/
communicationStatements
	: port Dot (portSendOp| portCallOp (portCallBody)? | portReplyOp | portRaiseOp
		     | portOrAnyStatement | portOrAllStatement)
	| AnyKeyword PortKeyword Dot (portOrAnyStatement)
	| AllKeyword PortKeyword Dot (portOrAllStatement)
	;
portOrAnyStatement
	: portReceiveOp
	| portTriggerOp
	| portGetCallOp
	| portGetReplyOp
	| portCatchOp
	| portCheckOp
	;
portOrAllStatement
	: portClearOp
	| portStartOp
	| portStopOp
	;

//sendStatement
//	: port Dot portSendOp
//	;
portSendOp
	: PortSendKeyword '(' sendParameter ')' (toClause)?
	;

sendParameter
	: templateInstance
	;
toClause
	: ToKeyword addressRef 
	| addressRefList
	| AllKeyword  ComponentKeyword
	;
addressRefList
	: '(' addressRef (',' addressRef)* ')'
	;

// static semantics - templateInstance must be of address or component type.
addressRef
	: templateInstance
	;
//callStatement
//	: port Dot portCallOp (portCallBody)?
//	;
portCallOp
	: CallOpKeyword '(' callParameters ')' (toClause)?
	;

// static semantics here
callParameters
	: templateInstance (',' callTimerValue)?
	;
callTimerValue
	: timerValue | NowaitKeyword
	;

portCallBody
	: '{' callBodyStatementList '}'
	;
callBodyStatementList
	: ( callBodyStatement SemiColon? )+
	;
callBodyStatement
	: callBodyGuard 
	  statementBlock
	;
callBodyGuard
	: altGuardChar callBodyOps
	;
callBodyOps
	//: getReplyStatement catchStatement
	: (port | AnyKeyword PortKeyword) Dot (portCatchOp |  portGetReplyOp)
	;
//replyStatement
//	: port Dot portReplyOp
//	;
portReplyOp
	: ReplyKeyword '(' templateInstance (replyValue)? ')' (toClause)?
	;

replyValue
	: ValueKeyword expression
	;

//raiseStatement
//	: port Dot portRaiseOp
//	;
portRaiseOp
	: RaiseKeyword '(' signature ',' templateInstance ')'  (toClause)?
	;


//receiveStatement
//	: portOrAny Dot portReceiveOp
//	;
//portOrAny
//	: port
//	| AnyKeyword PortKeyword
//	;
//static semantics here
portReceiveOp
	: ReceiveOpKeyword ('(' receiveParameter')')?  fromClause? portRedirect?
	;

receiveParameter
	: templateInstance
	;
fromClause
	: FromKeyword addressRef
	;

portRedirect
	: PortRedirectSymbol (valueSpec senderSpec? | senderSpec)?
	;

valueSpec
	: ValueKeyword variableRef
	;

senderSpec
	: SenderKeyword variableRef
	;


//triggerStatement
//	: portOrAny Dot portTriggerOp
//	;
//static semantics here
portTriggerOp
	: TriggerOpKeyword ('(' receiveParameter ')')? fromClause? portRedirect?
	;


//getCallStatement
//	: portOrAny Dot portGetCallOp
//	;
portGetCallOp
	: GetCallOpKeyword ('(' receiveParameter')')? fromClause? portRedirectWithParam?
	;

portRedirectWithParam
	: PortRedirectSymbol redirectWithParamSpec
	;
redirectWithParamSpec
	: paramSpec (senderSpec)?
	| senderSpec
	;
paramSpec
	: ParamKeyword paramAssignmentList
	;

paramAssignmentList
	: '(' (assignmentList | variableList ) ')'
	;
assignmentList
	: variableAssignment (',' variableAssignment)*
	;
//static semantics here
variableAssignment
	: variableRef AssignmentChar  parameterIdentifier
	;
parameterIdentifier
	: valueParIdentifier
	;
variableList
	: variableEntry (',' variableEntry)*
	;
variableEntry
	: variableRef | notUsedSymbol
	;

//getReplyStatement
//	: portOrAny Dot portGetReplyOp
//	;
//static semantics here
portGetReplyOp
	: GetReplyOpKeyword ( '(' receiveParameter (valueMatchSpec)? ')' )? 
	  (fromClause)? (portRedirectWithValueAndParam)?
	;

portRedirectWithValueAndParam
	: PortRedirectSymbol redirectWithValueAndParamSpec
	;
redirectWithValueAndParamSpec
	: valueSpec (paramSpec)? (senderSpec)?
	| redirectWithParamSpec
	;
valueMatchSpec
	: ValueKeyword templateInstance
	;

//checkStatement
//	: portOrAny Dot portCheckOp
//	;
portCheckOp
	: CheckOpKeyword ('(' checkParameter')')?
	;

checkParameter
	: checkPortOpsPresent
	| fromClausePresent
	| redirectPresent
	;
fromClausePresent
	: fromClause (PortRedirectSymbol senderSpec)?
	;
redirectPresent
	: PortRedirectSymbol senderSpec
	;
checkPortOpsPresent
	: portReceiveOp
	| portGetCallOp
	| portGetReplyOp
	| portCatchOp
	;

//catchStatement
//	: portOrAny Dot portCatchOp
//	;
//static semantics here
portCatchOp
	: CatchOpKeyword ('(' catchOpParameter')')?  fromClause? portRedirect?
	;

catchOpParameter
	: signature ',' templateInstance
	| TimeoutKeyword
	;
	
//clearStatement
//	: portOrAll Dot portClearOp
//	;
//portOrAll
//	: AllKeyword PortKeyword
//	| port
//	;
portClearOp
	: ClearOpKeyword
	;

	
//startStatement
//	: portOrAll Dot portStartOp
//	;
portStartOp
	: StartKeyword;


//stopStatement
//	: portOrAll Dot portStopOp
//	;
portStopOp
	: StopKeyword;

	 

/**
 * Timer Operations
 */
timerStatements
	: startTimerStatement
	| stopTimerStatement
	| timeoutStatement
	;
timerOps
	: readTimerOp
	| runningTimerOp
	;
startTimerStatement
	: timerRef Dot StartKeyword ('(' timerValue ')')?
	;
stopTimerStatement
	: timerRefOrAll Dot StopKeyword
	;
timerRefOrAll 
	: timerRef
	| AllKeyword TimerKeyword
	;
readTimerOp
	: timerRef Dot ReadKeyword
	;

runningTimerOp
	: timerRefOrAny Dot RunningKeyword
	;
timeoutStatement
	: timerRefOrAny Dot TimeoutKeyword
	;
timerRefOrAny
	: timerRef
	| AnyKeyword TimerKeyword
	;



/**
 * Type
 */

type
	: predefinedType | referencedType
	;

predefinedType
	: BitStringKeyword
	| BooleanKeyword
	| CharStringKeyword
	| UniversalCharString
	| IntegerKeyword
	| OctetStringKeyword
	| HexStringKeyword
	| VerdictTypeKeyword
	| FloatKeyword
	| AddressKeyword
	| DefaultKeyword
	| AnyTypeKeyword
	;

UniversalCharString
	:	UniversalKeyword CharStringKeyword
	;

referencedType
	: (globalModuleId Dot)? typeReference (extendedFieldReference)?
	;
typeReference
	: structTypeIdentifier (typeActualParList)?
	| enumTypeIdentifier
	| subTypeIdentifier
	| componentTypeIdentifier
	;
typeActualParList
	: '(' typeActualPar (',' typeActualPar)* ')'
	;
typeActualPar
	: constantExpression
	;
arrayDef
	: ( '[' arrayBounds ('..' arrayBounds)? ']')+
	;
//static semantics here
arrayBounds
	: singleConstExpression
	;

/**
  * value 
  */
value 
	: referencedValue
	| predefinedValue
	;
predefinedValue
	: Number	//integerValue
	| floatValue
	| charStringValue
	| bitStringValue
	| octetStringVlaue
	| hexStringValue
	| verdictTypeValue
	| enumeratedValue
	| booleanValue
	| AddressValue
	| 'omit'	//OmitValue
	;
bitStringValue
	:	Bstring;
booleanValue
	:	'true' | 'false';
//integerValue
//	:	Number;
octetStringVlaue
	:	Ostring;
hexStringValue
	:	Hstring;
verdictTypeValue
	:	'pass' | 'fail' | 'inconc' | 'none' | 'error';
enumeratedValue
	:	enumerationIdentifier;
charStringValue
	:	Cstring | quadruple;
quadruple
	:	CharKeyword '(' group ',' plane ',' row ',' cell ')'
	;

group
	:	Number;
plane
	:	Number;
row	:	Number;
cell	:	Number;

floatValue
	:	Number (Exponent | Dot DecimalNumber Exponent?) 
	;

Exponent	:	(('E') ( '-' )? Number);

referencedValue
	:	valueReference (extendedFieldReference)?
	;
valueReference
	:	(globalModuleId Dot)? (constIdentifier | extConstIdentifier | moduleParIdentifier)
	|	valueParIdentifier
	|	varIdentifier
	;
Number
	:	NonZeroNumber Num*
	|	'0'
	;

DecimalNumber
	:	Number+	//('0'..'9')+
	;
fragment
NonZeroNumber
	:	'1'..'9'
	;
fragment
Num	:	'0'..'9'
	;
Bstring
	:	'\'' Bin* '\'' B;
fragment
B
	:	'B';

fragment
Bin	:	'0' | '1'
	;
Hstring
	:	'\'' Hex* '\'' H;
fragment
H
	:	'H';
fragment
Hex	:	Num | 'a'..'z' | 'A' .. 'Z';

Ostring
	:	'\'' Oct '\'' O;
fragment
O
	:	'O';

fragment
Oct	:	Hex Hex
	;
// Note here
Cstring
	//:	'"' Char* '"';
	: '"' ( EscapeSequence | ~('\\'|'"') )* '"'
	;


fragment
EscapeSequence
	:	'\\' ('b'|'t'|'n'|'f'|'r'|'\"'|'\''|'\\')
	;

ID
	:  ('a'..'z'|'A'..'Z') ('a'..'z'|'A'..'Z'|'0'..'9'|'_')* 
	;

// note here
//ExtendedAlphaNum
//	:	Cstring; //'\x20'..'\x7E';
	
freeText
	:	Cstring//'"' ExtendedAlphaNum  '"'
	;

formalValuePar
	:	(InParKeyword | OutParKeyword | InOutParKeyword)? type valueParIdentifier
	;
valueParIdentifier
	:	ID;
formalPortPar
	:	(InOutParKeyword)? portTypeIdentifier portParIdentifier
	;
portParIdentifier
	:	ID;
formalTimerPar
	:	(InOutParKeyword)? TimerKeyword timerParIdentifier
	;
timerParIdentifier
	:	ID;
formalTemplatePar
	:	(InParKeyword | OutParKeyword | InOutParKeyword)? 
		TemplateKeyword type templateParIdentifier
	;
templateParIdentifier
	:	ID;


/**
 *With statements
 */
withStatement
	:	WithKeyword withAttribList
	;

withAttribList
	:	'{' multiWithAttrib '}'
	;
multiWithAttrib
	:	(singleWithAttrib (SemiColon)? )*
	;
singleWithAttrib
	:	attribKeyword (OverrideKeyword)? (attribQualifier)? attribSpec
	;
attribKeyword
	:	EncodeKeyword
	|	VariantKeyword
	|	DisplayKeyword
	|	ExtensionKeyword
	;

attribQualifier
	:	'(' defOrFieldRefList ')'
	;
defOrFieldRefList
	:	defOrFieldRef (',' defOrFieldRef)*
	;
//static semantics here
defOrFieldRef
	:	definitionRef
	|	fieldReference
	|	allRef
	;
definitionRef
	:	structTypeIdentifier
	|	enumTypeIdentifier
	|	portTypeIdentifier
	|	componentTypeIdentifier
	|	subTypeIdentifier
	|	constIdentifier
	|	templateIdentifier
		|	altstepIdentifier
	|	testcaseIdentifier
	|	functionIdentifier
	|	signatureIdentifier
	|	varIdentifier
	|	timerIdentifier
	|	portIdentifier
	|	moduleParIdentifier
	|	fullGroupIdentifier
	;
allRef
	:	(GroupKeyword AllKeyword (ExceptKeyword '{' groupRefList '}')? )?
	|	(TypeDefKeyword AllKeyword (ExceptKeyword '{' typeRefList '}')? )?
	|	(TemplateKeyword AllKeyword (ExceptKeyword '{' templateRefList '}')? )?
	|	(ConstKeyword AllKeyword (ExceptKeyword '{' constRefList '}')? )?
	|	(AltstepKeyword AllKeyword (ExceptKeyword '{' altstepRefList '}')? )?
	|	(TestcaseKeyword AllKeyword (ExceptKeyword '{' testcaseRefList '}')? )?
	|	(FunctionKeyword AllKeyword (ExceptKeyword '{' functionRefList '}')? )?
	|	(SignatureKeyword AllKeyword (ExceptKeyword '{' signatureRefList '}')? )?
	|	(ModuleParKeyword AllKeyword (ExceptKeyword '{' moduleParRefList '}')? )?
	;
attribSpec
	:	freeText
	;

/**
 *Behaviour statements
 */
//static semantics here
behaviourStatements
	:	testcaseInstance
	|	functionInstance
	|	returnStatement
	|	altConstruct
	|	interleavedConstruct
	|	labelStatement
	|	gotoStatement
	|	repeatStatement
	|	deactivateStatement
	|	altstepInstance
	|	activateOp
	;

verdictStatements
	:	setLocalVerdict
	;
verdictOps
	:	GetLocalVerdict
	;
//static semantics here
setLocalVerdict
	:	SetVerdictKeyword '(' singleExpression ')'
	;

sUTStatements
	:	ActionKeyword '(' actionText ( '&' actionText)* ')'
	;

//static semantics here
actionText
	:	freeText
	|	expression
	;

returnStatement
	:	ReturnKeyword (expression)?
	;
altConstruct
	:	AltKeyword '{' altGuardList '}'
	;

altGuardList
	:	( (guardStatement | elseStatement) SemiColon? )*
	;
guardStatement
	:	altGuardChar ( altstepInstance (statementBlock)? | guardOp statementBlock )
	;
elseStatement
	:	'[' ElseKeyword']'  statementBlock
	;
//static semantics here
altGuardChar
	:	'[' (booleanExpression)? ']'
	;
//static semantics here
/*
guardOp
	:	(timerRefOrAny Dot TimeoutKeyword) => timeoutStatement
	|	(portOrAny Dot ReceiveOpKeyword) => receiveStatement
	|	(portOrAny Dot TriggerOpKeyword) =>triggerStatement
	|	(portOrAny Dot CallOpKeyword) =>getCallStatement
	|	(portOrAny Dot CatchOpKeyword) =>catchStatement
	|	(portOrAny Dot CheckOpKeyword) =>checkStatement
	|	(portOrAny Dot GetReplyOpKeyword) =>getReplyStatement
	|	(componentID Dot DoneKeyword) =>doneStatement
	|	killedStatement
	;
*/
guardOp
	:	(port |AnyKeyword PortKeyword) Dot portOrAnyStatement
	|	timeoutStatement
	|	doneStatement
	|	killedStatement
	;

interleavedConstruct
	:	InterleavedKeyword '{' interleavedGuardList '}'
	;

interleavedGuardList
	:	(interleavedGuardElement (SemiColon)? )*
	;
interleavedGuardElement
	:	interleavedGuard interleavedAction
	;
interleavedGuard
    : '[' ']' guardOp
	;
//static semantics here
interleavedAction
	:	statementBlock
	;

labelStatement
	:	LabelKeyword labelIdentifier
	;

labelIdentifier
	:	ID;

gotoStatement
	:	GotoKeyword labelIdentifier
	;


repeatStatement
	:	'repeat';

activateOp
	:	ActivateKeyword '(' altstepInstance ')'
	;


deactivateStatement
	:	DeactivateKeyword ('(' componentOrDefaultReference ')')?
	;



/**
 *Basic statements
 */
basicStatements
	:	assignment
	|	logStatement
	|	loopConstruct
	|	conditionalConstruct
	|	selectCaseConstruct
	;
//static semantics here
expression
	:	singleExpression
	|	compoundExpression
	;
compoundExpression
	:	fieldExpressionList
	|	arrayExpression
	;
fieldExpressionList
	:	'{' fieldExpressionSpec (',' fieldExpressionSpec)* '}'
	;
fieldExpressionSpec
	:	fieldReference AssignmentChar notUsedOrExpression
	;
arrayExpression
	:	'{' arrayElementExpressionList '}'
	;
arrayElementExpressionList
	:	notUsedOrExpression (',' notUsedOrExpression)*
	;
notUsedOrExpression
	:	notUsedSymbol
	|	expression
	;

constantExpression
	:	singleConstExpression
	|	compoundConstExpression
	;
//static semantics here
singleConstExpression
	:	singleExpression
	;
//static semantics here
compoundConstExpression
	:	fieldConstExpressionList
	|	arrayConstExpression
	;
fieldConstExpressionList
	:	'{' fieldConstExpressionSpec (',' fieldConstExpressionSpec)* '}'
	;
fieldConstExpressionSpec
	:	fieldReference AssignmentChar constantExpression
	;
arrayConstExpression
	:	'{' arrayElementConstExpressionList? '}'
	;
arrayElementConstExpressionList
	:	constantExpression (',' constantExpression)*
	;

// static semantics here
booleanExpression
	:	singleExpression
	;

//static semantics here
assignment
	:	variableRef AssignmentChar (expression | templateBody)
	;

//some static semantics here
singleExpression
	:	xorExpression ('or' xorExpression)*
	;
xorExpression
	:	andExpression ('xor' andExpression)*
	;
andExpression
	:	notExpression ('and' notExpression)*
	;
notExpression
	:	('not')? equalExpression
	;
equalExpression
	:	relExpression (equalOp relExpression)*
	;
relExpression
	:	shiftExpression (relOp shiftExpression)?
	;
shiftExpression
	:	bitOrExpression (shiftOp bitOrExpression)*
	;
bitOrExpression
	:	bitXorExpression ('or4b' bitXorExpression)*
	;
bitXorExpression
	:	bitAndExpression ('xor4b' bitAndExpression)*
	;
bitAndExpression
	:	bitNotExpression ('and4b' bitNotExpression)*
	;
bitNotExpression
	:	('not4b')? addExpression
	;
addExpression
	:	mulExpression ( addOp mulExpression)*
	;
mulExpression
	:	unaryExpression ( multiplyOp  unaryExpression)*
	;
unaryExpression
	:	unaryOp? primary
	;
primary
	:	opCall
	|	value
	|	'(' singleExpression ')'
	;
extendedFieldReference
	:	( Dot (structFieldIdentifier | typeDefIdentifier) 
	            | arrayOrBitRef
	           )+
	;
opCall
	:	configurationOps
	|	verdictOps
	|	timerOps
	|	testcaseInstance
	|	functionInstance
	|	templateOps
	|	activateOp
	;

logStatement
	:	LogKeyword '(' logItem (',' logItem)* ')'
	;

logItem
	:	freeText
	|	templateInstance
	;

loopConstruct
	:	forStatement
	|	whileStatement
	|	doWhileStatement
	;
forStatement
	:	ForKeyword '(' initialexpr SemiColon finalcondition SemiColon stepexpr ')' statementBlock
	;

initialexpr
	:	varInstance
	|	assignment
	;
finalcondition
	:	booleanExpression
	;
stepexpr:		assignment
	;

whileStatement
	:	WhileKeyword '(' booleanExpression ')' statementBlock
	;

doWhileStatement
	:	DoKeyword statementBlock WhileKeyword '(' booleanExpression ')'
	;

conditionalConstruct
	:	IfKeyword '(' booleanExpression ')' statementBlock
		(options{greedy=true;}:elseIfClause)* (elseClause)?
	;

elseIfClause
	:	ElseKeyword IfKeyword '(' booleanExpression ')' statementBlock
	;
elseClause
	:	ElseKeyword statementBlock
	;

	
selectCaseConstruct
	:	SelectKeyword '(' singleExpression ')' selectCaseBody
	;

selectCaseBody
	:	'{' selectCase+ '}'
	;
selectCase
	:	CaseKeyword ( '(' templateInstance (',' templateInstance)* ')' | ElseKeyword )
		 statementBlock
	;


/**
 * Miscellaneous productions
 */

addOp
	:	'+' | '-' | '&'	;
multiplyOp 
	:	  '*' | '/' | 'mod' | 'rem' ;
unaryOp
	:	'+' | '-'
	;
relOp 
	:	 '<' | '>' | '<=' | '>=' ;
equalOp 
	:	 '==' | '!=' ;
shiftOp 
	:	'<<' | '>>' | '<@' | '@>' ;

WS	: ('\t' | ' ' | '\r' | '\n' )+ {$channel=HIDDEN;}
	;

COMMENT
    :   '/*' ( options {greedy=false;} : . )* '*/' {$channel=HIDDEN;}
    ;

LINE_COMMENT
    : '//' ~('\n'|'\r')* '\r'? '\n' {$channel=HIDDEN;}
    ;
